package com.scwatch.core.html;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.scwatch.common.file.FileHandler;
import com.scwatch.common.util.Dates;
import com.scwatch.common.web.PathResolver;
import com.scwatch.core.constant.Constants;
import com.scwatch.core.domain.*;
import com.scwatch.core.service.InfoDetailService;
import com.scwatch.core.service.InfoService;
import com.scwatch.core.service.SpecialService;
import com.scwatch.core.service.TaskService;
import com.scwatch.core.support.Context;
import com.scwatch.core.support.ForeContext;
import com.scwatch.core.thirdapi.UserSystemApi;
import com.scwatch.ext.domain.*;
import com.scwatch.ext.service.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.IOException;
import java.util.*;

public class HtmlGeneratorImpl implements HtmlGenerator {
	private final Logger logger = LoggerFactory.getLogger(HtmlGeneratorImpl.class);

	private static final int INFO_MAX_RESULT = 200;
	private static final int NODE_MAX_RESULT = 200;

	public void makeAll(final Integer siteId, String siteName, final Integer userId, final boolean forUpdate) {
		if (StringUtils.isBlank(siteName)) {
			siteName = siteId.toString();
		}
		Task task = taskService.save("Site: " + siteName, null, Task.NODE_HTML, userId, siteId);
		final Integer taskId = task.getId();
		new Thread() {
			public void run() {
				Integer lastId;
				try {
					lastId = null;
					do {
						lastId = htmlService.makeNode(siteId, null, true, taskId, forUpdate, lastId, NODE_MAX_RESULT,null);
					} while (lastId != null);

					lastId = null;
					do {
						lastId = htmlService.makeInfo(siteId, null, true, taskId, forUpdate, lastId, INFO_MAX_RESULT);
					} while (lastId != null);
					taskService.finish(taskId);
				} catch (Exception e) {
					taskService.abort(taskId);
					logger.error("make html error!", e);
				}
			}
		}.start();
	}

	public void makeInfo(final Integer siteId, final Integer nodeId, String nodeName, final boolean includeChildren,
			Integer userId) {
		if (StringUtils.isNotBlank(nodeName)) {
			nodeName = "ALL";
		}
		Task task = taskService.save("Node: " + nodeName, null, Task.INFO_HTML, userId, siteId);
		final Integer taskId = task.getId();
//		new Thread() {
//			public void run() {
				try {
					Integer lastId = null;
					do {
						lastId = htmlService.makeInfo(siteId, nodeId, includeChildren, taskId, false, lastId,
								INFO_MAX_RESULT);
					} while (lastId != null);
					taskService.finish(taskId);
				} catch (Exception e) {
					taskService.abort(taskId);
					logger.error("make html error!", e);
				}
//			}
//		}.start();
	}

	public void makeNode(final Integer siteId, final Integer nodeId, String nodeName, final boolean includeChildren,
                         Integer userId, final String queryDate) {
		if (StringUtils.isNotBlank(nodeName)) {
			nodeName = "ALL";
		}
		Task task = taskService.save("Node: " + nodeName, null, Task.NODE_HTML, userId, siteId);
		final Integer taskId = task.getId();
//		new Thread() {
//			public void run() {
				try {
					Integer lastId = null;
					do {
						htmlService.makeNode(siteId, nodeId, includeChildren, taskId, false, lastId, NODE_MAX_RESULT,queryDate);
					} while (lastId != null);
					taskService.finish(taskId);
				} catch (Exception e) {
					taskService.abort(taskId);
					logger.error("make html error!", e);
				}
//			}
//		}.start();
	}

	public void deleteHtml(Node node) {
		if (node == null) {
			return;
		}
		Site site = node.getSite();
		String filename = node.getUrlStatic(0, false, true, false);
		FileHandler fileHandler = site.getHtmlPublishPoint().getFileHandler(pathResolver);
		fileHandler.delete(filename);
		// 手机端域名存在，并且手机端发布点与PC端发布点不相同
		if (StringUtils.isNotBlank(site.getMobileDomain())
				&& !site.getHtmlPublishPoint().getId().equals(site.getMobilePublishPoint().getId())) {
			filename = node.getUrlStatic(1, false, true, true);
			fileHandler = node.getSite().getHtmlPublishPoint().getFileHandler(pathResolver);
			fileHandler.delete(filename);
		}
	}

    @Override
    public void generationStartPage(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        Pageable pageable=new PageRequest(0,1000, Sort.Direction.ASC,"sort");
//        public PageRequest(int page, int size, Direction direction, String... properties) {
//            this(page, size, new Sort(direction, properties));
//        }
        params.put("EQ_isStart",new String[]{"1"});
        Page<StartPage> pagedList = startPageService.findAll(site.getId(), params, pageable);
        for(StartPage page : pagedList){
            List<String> newsUrl = new ArrayList<>();
            if(page.getRelateNews()!=null && !page.getRelateNews().equals("")){
                String news = page.getRelateNews().substring(1,page.getRelateNews().length()-1);
                if(news!=null && !news.equals("")){
                    String [] relateNews = news.replace("\"","").split(",");
                    for(String relate : relateNews){
                        String[] ids = relate.split(":");
                        Info detail = infoService.getInfoById(Integer.valueOf(ids[0]));
                        newsUrl.add(detail.getUrl());
                    }
                }
            }

            page.setNewsUrl(newsUrl);
        }
        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("startPageList",pagedList.getContent());
        String tp=rootnode.getSite().getTemplate("/json/start_page.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/startPage.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationAppversion(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        Pageable pageable=new PageRequest(0,1, Sort.Direction.DESC,"createDate");
//        public PageRequest(int page, int size, Direction direction, String... properties) {
//            this(page, size, new Sort(direction, properties));
//        }
        params.put("EQ_publish",new String[]{"1"});
        Page<AppVersion> pagedList = appVersionService.findAll(site.getId(), params, pageable);
        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("appVersionList",pagedList.getContent());
        String tp=rootnode.getSite().getTemplate("/json/appVersion.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/appVersion.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationSpec(Site site,Integer specId,Node rootnode) {
        Special special=specialService.get(specId);
        Map<String, Object> rootMap = new HashMap<String, Object>();

        String rootUrl=rootnode.getDomainPath();
        ForeContext.setData(rootMap, site, null, null, null, null, null, null, null);
        try {

            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            //子专题
            //详情json
            String childSpecTp=rootnode.getSite().getTemplate("/json/spec_info.ftl");
            Template childTemplate=getConfig().getTemplate(childSpecTp);
            //分享h5
            String childShared = rootnode.getSite().getTemplate("/h5/opic_page_shared.html");
            Template childSpecsharedTemplate =getConfig().getTemplate(childShared);
            List<Special> childSpeclist=new ArrayList<>();
            for(Special childSpec:special.getChildren()){
                //正常状态（非回收站）
                if(childSpec.getRecycleState()!=null &&childSpec.getRecycleState().intValue()==0){
                    String childFilename="/spec/"+childSpec.getId()+".json";

                    //childFilename进行时间判断,大于分割日期，按照年月日路径生成
                    Date divisionDate= Dates.formatDateStr(Constants.DIVISIONDATE,"yyyy-MM-dd HH:mm:ss");
                    if(childSpec.getCreationDate()!=null &&  childSpec.getCreationDate().compareTo(divisionDate)>0){
                        childFilename="/spec/{year}/{month}/{day}/"+childSpec.getId()+".json";
                        Calendar now = Calendar.getInstance();
                        now.setTime(childSpec.getCreationDate());
                        String year = String.valueOf(now.get(Calendar.YEAR));
                        int m = now.get(Calendar.MONTH) + 1;
                        int d = now.get(Calendar.DAY_OF_MONTH);
                        String month = StringUtils.leftPad(String.valueOf(m), 2, '0');
                        String day = StringUtils.leftPad(String.valueOf(d), 2, '0');
                        childFilename = StringUtils.replace(childFilename, "{year}", year);
                        childFilename = StringUtils.replace(childFilename, "{month}", month);
                        childFilename = StringUtils.replace(childFilename, "{day}", day);
                    }

                    String childSpecsharedFileName = childFilename.replaceFirst(".json", "_shared.html");
                    rootMap.put("special",childSpec);
                    rootMap.put("specSharedUrl",rootUrl+childSpecsharedFileName);

                    fileHandler.storeFile(childSpecsharedTemplate, rootMap, childSpecsharedFileName);
                    fileHandler.storeFile(childTemplate, rootMap, childFilename);
                    //保存json url
                    childSpec.setJsonUrl(rootUrl+childFilename);
                    childSpec.setPublish(0);
                    specialService.updateSpecial(childSpec);
                    childSpeclist.add(childSpec);
                }
            }
            //父专题 生成
            //详情
            String parentSpecTp=rootnode.getSite().getTemplate("/json/parent_spec_info.ftl");
            Template parentTemplate=getConfig().getTemplate(parentSpecTp);
            String parentFilename="/spec/"+special.getId()+".json";
            //parentFilename进行时间判断,大于分割日期，按照年月日路径生成
            Date divisionDate= Dates.formatDateStr(Constants.DIVISIONDATE,"yyyy-MM-dd HH:mm:ss");
            if(special.getCreationDate()!=null &&  special.getCreationDate().compareTo(divisionDate)>0){
                parentFilename="/spec/{year}/{month}/{day}/"+special.getId()+".json";
                Calendar now = Calendar.getInstance();
                now.setTime(special.getCreationDate());
                String year = String.valueOf(now.get(Calendar.YEAR));
                int m = now.get(Calendar.MONTH) + 1;
                int d = now.get(Calendar.DAY_OF_MONTH);
                String month = StringUtils.leftPad(String.valueOf(m), 2, '0');
                String day = StringUtils.leftPad(String.valueOf(d), 2, '0');
                parentFilename = StringUtils.replace(parentFilename, "{year}", year);
                parentFilename = StringUtils.replace(parentFilename, "{month}", month);
                parentFilename = StringUtils.replace(parentFilename, "{day}", day);
            }


            //分享
            String parentSpecSharedTp=rootnode.getSite().getTemplate("/h5/opic_parent_page_shared.html");
            Template parentSpecSharedTemplate=getConfig().getTemplate(parentSpecSharedTp);
            String parentSpecSharedFilename=parentFilename.replaceFirst(".json", "_shared.html");

            rootMap.put("parentSpecial",special);
            rootMap.put("parentSpecSharedUrl",rootUrl+parentSpecSharedFilename);
            rootMap.put("childSpeclist",childSpeclist);

            fileHandler.storeFile(parentSpecSharedTemplate, rootMap, parentSpecSharedFilename);
            fileHandler.storeFile(parentTemplate, rootMap, parentFilename);
            //保存json url
            special.setJsonUrl(rootUrl+parentFilename);
            specialService.updateSpecial(special);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationQrcode(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        Pageable pageable=new PageRequest(0,1, Sort.Direction.DESC,"createDate");
//        public PageRequest(int page, int size, Direction direction, String... properties) {
//            this(page, size, new Sort(direction, properties));
//        }
        params.put("EQ_publish",new String[]{"1"});
        Page<Qrcode> pagedList = qrcodeService.findAll(site.getId(), params, pageable);
        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("qrcodeList",pagedList.getContent());
        String tp=rootnode.getSite().getTemplate("/json/qrCode.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/qrCode.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationAdvertisement(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        Pageable pageable=new PageRequest(0,10, Sort.Direction.DESC,"createDate");
//        public PageRequest(int page, int size, Direction direction, String... properties) {
//            this(page, size, new Sort(direction, properties));
//        }
        params.put("EQ_publish",new String[]{"1"});
        Page<Advertisement> pagedList = advertisementService.findAll(site.getId(), params, pageable);
        for(Advertisement page : pagedList){
            List<String>  newsUrl = new ArrayList<>();
            if(page.getRelateNews()!=null && !page.getRelateNews().equals("")){
                String news = page.getRelateNews().substring(1,page.getRelateNews().length()-1);
                if(news!=null && !news.equals("")){
                    String [] relateNews = news.replace("\"","").split(",");
                    for(String relate : relateNews){
                        String[] ids = relate.split(":");
                        Info detail = infoService.getInfoById(Integer.valueOf(ids[0]));
                        newsUrl.add(detail.getUrl());
                    }
                }
            }
            if(page.getAdType().equals(2)){//关联商品
                Map<String,Object> map = new HashMap<>();
                UserSystemApi userSystemApi = new UserSystemApi();
                map.put("pageIndex",0);
                map.put("productId",page.getProductCode());
                map.put("productName",null);
                JSONObject result = userSystemApi.selectProductList(map);
                page.setProductJson(result.getJSONObject("data").get("jsonUrl").toString());
                String jumpUrl =result.getJSONObject("data").get("jumpUrl")==null?null:result.getJSONObject("data").get("jumpUrl").toString();
                if(StringUtils.isNotBlank(jumpUrl)){
                    page.setProductUrl(jumpUrl);
                    page.setProductType("2");
                }else{
                    page.setProductType("1");
                    page.setProductUrl(result.getJSONObject("data").get("h5Url").toString());
                }
            }

            page.setNewsUrl(newsUrl);
        }

        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("advertList",pagedList.getContent());
        String tp=rootnode.getSite().getTemplate("/json/advert.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/advert.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void deleteSpecHtml(Site site,Special spec) {
        if (spec != null && spec.getPublish()!=null && spec.getPublish().intValue()==1) {
            FileHandler fileHandler = site.getHtmlPublishPoint().getFileHandler(pathResolver);

            //子栏目
            List<Special> childs=spec.getChildren();
            if(childs!=null && childs.size()>0){
                for(Special child:childs){
                    String jsonUrl=child.getJsonUrl();
                    String sharedUrl=child.getChildSpecSharedHtml();
                    fileHandler.delete(jsonUrl);
                    fileHandler.delete(sharedUrl);
                }
            }

            String jsonUrl=spec.getJsonUrl();
            String sharedUrl=jsonUrl.replaceFirst(".json", "_shared.html");
            fileHandler.delete(jsonUrl);
            fileHandler.delete(sharedUrl);
        }
    }

    @Override
    public void generationLiveManage(Site site, LiveBroadcast live, Node rootnode) {
        String ctx = site.getContextPath();
        String rootUrl=rootnode.getDomainPath();
        Map<String, Object> rootMap = new HashMap<String, Object>();
        String liveDetailTp=rootnode.getSite().getTemplate("/json/livenode_detail.ftl");
        String liveSharedTp=rootnode.getSite().getTemplate("/h5/live_broadcast_shared.html");
        String filename="/lives/{year}/{month}/{day}/"+live.getId()+".json";
        Calendar now = Calendar.getInstance();
        now.setTime(live.getCreatetime());
        String year = String.valueOf(now.get(Calendar.YEAR));
        int m = now.get(Calendar.MONTH) + 1;
        int d = now.get(Calendar.DAY_OF_MONTH);
        String month = StringUtils.leftPad(String.valueOf(m), 2, '0');
        String day = StringUtils.leftPad(String.valueOf(d), 2, '0');
        filename = StringUtils.replace(filename, "{year}", year);
        filename = StringUtils.replace(filename, "{month}", month);
        filename = StringUtils.replace(filename, "{day}", day);
        try {
            Info info=new Info();
            info.setRefLive(live);
            Template liveDetailTemplate=getConfig().getTemplate(liveDetailTp);
            Template liveSharedTemplate=getConfig().getTemplate(liveSharedTp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);

            rootMap.put(Constants.CTX, ctx != null ? ctx : "");
            //直播分享页
            rootMap.put("info",info);
            String sharedFilename=filename.replaceFirst(".json", "_shared.html");
            fileHandler.storeFile(liveSharedTemplate, rootMap, sharedFilename);

            //json详情
            rootMap.put("liveSharedUrl", rootUrl+sharedFilename);
            fileHandler.storeFile(liveDetailTemplate, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void deleteLiveJson(Site site, LiveBroadcast live, Node rootnode) {
        if (live != null) {
            FileHandler fileHandler = site.getHtmlPublishPoint().getFileHandler(pathResolver);
            String rootUrl=rootnode.getDomainPath();
            String jsonUrl=rootUrl+live.getJsonUrl();
            String sharedUrl=rootUrl+live.getSharedUrl();
            fileHandler.delete(jsonUrl);
            fileHandler.delete(sharedUrl);
        }
    }

    @Override
    public void generationAppConfig(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        Pageable pageable=new PageRequest(0,1, Sort.Direction.DESC,"createDate");
//        public PageRequest(int page, int size, Direction direction, String... properties) {
//            this(page, size, new Sort(direction, properties));
//        }
        params.put("EQ_publish",new String[]{"1"});
        Page<AppService> pagedList = appConfigService.findAll(site.getId(), params, pageable);
        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("appconfigList",pagedList.getContent());
        String tp=rootnode.getSite().getTemplate("/json/appConfig.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/appConfig.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void generationCityConfig(Site site,Node rootnode) {
        Map<String, String[]> params =new HashMap<>();
        params.put("EQ_publish",new String[]{"1"});
        params.put("EQ_level",new String[]{"0"});
        List<CityConfig> oneCitys=cityConfigService.findList(site.getId(),params,new Sort(Sort.Direction.ASC,"seq"));
        Map<String, Object> rootMap = new HashMap<String, Object>();
        rootMap.put("oneCitys",oneCitys);
        String tp=rootnode.getSite().getTemplate("/json/cityConfig.ftl");
        try {
            Template template=getConfig().getTemplate(tp);
            PublishPoint publishPoint = Context.isMobile() ? rootnode.getSite().getMobilePublishPoint() : rootnode.getSite()
                    .getHtmlPublishPoint();
            FileHandler fileHandler = publishPoint.getFileHandler(pathResolver);
            String filename="/cityConfig.json";

            fileHandler.storeFile(template, rootMap, filename);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private FreeMarkerConfigurer freeMarkerConfigurer;
    private PathResolver pathResolver;
	private HtmlService htmlService;
	private TaskService taskService;

    private AppVersionService appVersionService;

    private StartPageService startPageService;

    @Autowired
    private SpecialService specialService;

    @Autowired
    private QrcodeService qrcodeService;

    @Autowired
    private AdvertisementService advertisementService;

    @Autowired
    private AppConfigService appConfigService;
    @Autowired
    private CityConfigService cityConfigService;

//    @Autowired
//    private InfoDetailService infoDetailService;

    @Autowired
    private InfoService infoService;


    @Autowired
    public void setAppVersionService(AppVersionService appVersionService) {
        this.appVersionService = appVersionService;
    }

    @Autowired
    public void setStartPageService(StartPageService startPageService) {
        this.startPageService = startPageService;
    }

	@Autowired
	public void setPathResolver(PathResolver pathResolver) {
		this.pathResolver = pathResolver;
	}

	@Autowired
	public void setHtmlService(HtmlService htmlService) {
		this.htmlService = htmlService;
	}

	@Autowired
	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

    private Configuration getConfig() {
        return freeMarkerConfigurer.getConfiguration();
    }
    @Autowired
    public void setFreeMarkerConfigurer(
            FreeMarkerConfigurer freeMarkerConfigurer) {
        this.freeMarkerConfigurer = freeMarkerConfigurer;
    }
}
